﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Windows;
using Store.WP7.Data;
using Store.WP7.Data.WebStore;
using Store.WP7.Framework;
using Store.WP7.Framework.ErrorManagement;
using Store.WP7.Framework.Settings;
using Microsoft.Phone.Shell;

namespace Store.WP7.ViewModels
{
    public class CheckOutViewModel : PageViewModelBase
    {
        /// <summary>
        /// TODO Refactoring : mettre StoreService et AppSettings au niveau du PageViewModelBase 
        /// </summary>
        #region Private Fields

        private StoreService _storeService;
        private AppSettings _appSettings;
        private Customer _Customer;
        private bool _areProductsLoaded = false;
        private bool _areAddressesLoaded = false;

        private bool IsDataLoaded { get { return _areProductsLoaded && _areAddressesLoaded; } }

        #endregion

        #region Ctors

        public CheckOutViewModel()
        {
        }

        #endregion

        #region Public Properties

        private int _PickerSelectedIndex;
        public int PickerSelectedIndex
        {
            get { return _PickerSelectedIndex; }
            set
            {
                if (_PickerSelectedIndex != value)
                {
                    _PickerSelectedIndex = value;
                    System.Diagnostics.Debug.WriteLine(string.Format("PickerSelectedIndex : {0}", value));
                    RaisePropertyChanged(() => PickerSelectedIndex);
                }
            }
        }

        private bool _WantToAddNewAddress = false;
        public bool WantToAddNewAddress
        {
            get { return _WantToAddNewAddress; }
            set
            {
                _WantToAddNewAddress = value;
                RaisePropertyChanged(() => WantToAddNewAddress);
            }
        }

        private string _TotalPrice;
        public string TotalPrice
        {
            get { return _TotalPrice; }
            set
            {
                if (_TotalPrice != value)
                {
                    _TotalPrice = value;
                    RaisePropertyChanged(() => TotalPrice);
                }
            }
        }

        private Address _NewAddress;
        public Address NewAddress
        {
            get { return _NewAddress; }
            set
            {
                _NewAddress = value;
                RaisePropertyChanged(() => NewAddress);
            }
        }

        private Address _SelectedAddress;
        public Address SelectedAddress
        {
            get { return _SelectedAddress; }
            set
            {
                _SelectedAddress = value;
                RaisePropertyChanged(() => SelectedAddress);
            }
        }

        private ObservableCollection<Address> _Addresses = new ObservableCollection<Address>();
        public ObservableCollection<Address> Addresses
        {
            get { return _Addresses; }
        }

        private readonly ObservableCollection<ProductViewModel> _products = new ObservableCollection<ProductViewModel>();
        public ObservableCollection<ProductViewModel> Products
        {
            get
            {
                return _products;
            }
        }

        #endregion

        #region Public Methods

        public override void OnNavigatedTo(System.Windows.Navigation.NavigationService navigationService, System.Windows.Navigation.NavigationContext navigationContext, IDictionary<string, object> state, System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(navigationService, navigationContext, state, e);

            if (!IsDataLoaded)
            {
                _storeService = new StoreService();
                _appSettings = AppSettings.Load();
                LoadCustomer();
                LoadProducts();
                NewAddress = new Address();

                RestoreState(state);
            }
        }

        public override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e, IDictionary<string, object> state)
        {
            base.OnNavigatingFrom(e, state);

            if (e.NavigationMode != System.Windows.Navigation.NavigationMode.Back) 
            {
                SaveState(state);
            }
        }

        #region Tombstoning

        private void RestoreState(IDictionary<string, object> state)
        {
            if (state.Count > 0)
            {
                if (state.ContainsKey("NewAddress"))
                    NewAddress = state["NewAddress"] as Address;

                if (state.ContainsKey("WantToAddNewAddress"))
                    WantToAddNewAddress = (bool)state["WantToAddNewAddress"];
            }
        }

        private void SaveState(IDictionary<string, object> state)
        {
            state["NewAddress"] = NewAddress;
            state["WantToAddNewAddress"] = WantToAddNewAddress;
        }

        #endregion


        public void OnGoToCreateAddress()
        {
            WantToAddNewAddress = true;
        }

        public void OnAutoFillAddress()
        {
            NewAddress = new Address
            {
                Label = "Boulot 2",
                FirstName = _Customer.FirstName,
                LastName = _Customer.LastName,
                Street = "41 Quai du Président Roosevelt",
                City = "Issy-Les-Moulineaux",
                ZipCode = 92130
            };
        }

        public void OnCreateAndSetAddress()
        {
            IsBusy = true;

            if (NewAddress != null)
            {
                _storeService.AddCustomerAddressAsync(_Customer.Id, NewAddress, callback =>
                {
                    if (callback.Error == null)
                    {

                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            NewAddress = new Address();
                            IsBusy = false;
                            WantToAddNewAddress = false;

                            LoadCustomer(0);
                        });
                    }
                    else
                    {
                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            IsBusy = false;
                            ErrorManager.HandleError(ErrorType.WebServiceCallbackFail, callback.Error);
                        });
                    }
                });
            }
        }

        public void OnCancelCreateAddress()
        {
            NewAddress = new Address();
            WantToAddNewAddress = false;
        }

        public void OnSubmitOrder()
        {
            // TODO: Hack temporaire pour la démo
            return;

            IsBusy = true;

            //building order
            Order o = new Order();
            //o.Customer = _Customer; //we should not need that;
            o.CustomerId = _Customer.Id;
            o.ShipAddress = Addresses[PickerSelectedIndex];
            o.Products = new List<Product>();

            foreach (var p in Products)
            {
                o.TotalPrice += p.InnetProduct.Price;
                o.Products.Add(p.InnetProduct);
            }

            _storeService.SubmitOrderAsync(o, callback =>
            {
                if (callback.Error == null)
                {
                    CacheManager.Current.Remove(AppSettingsKeyNames.Basket);

                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        NavigationService.Navigate(new System.Uri("/Views/MainPage.xaml?go=orders", System.UriKind.Relative));
                    });
                }
                else
                {
                    //TODO
                }
            });
        }

        #endregion

        #region Private Methods

        private void LoadCustomer(int index = -1)
        {
            SelectedAddress = null;
            PickerSelectedIndex = -1;

            _storeService.LoadCustomerAsync(_appSettings.CustomerId, callback =>
            {
                if (callback.Error == null)
                {
                    _Customer = callback.Result;
                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        _Addresses.Clear();
                    });

                    foreach (var address in _Customer.Addresses)
                    {
                        Address a = address;
                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            Addresses.Add(a);
                        });
                    }

                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        PickerSelectedIndex = 0;
                        IsBusy = false;
                        _areAddressesLoaded = true;
                    });
                }
                else
                {
                    // TODO
                }
            });
        }

        private void LoadProducts()
        {
            var basketProducts = CacheManager.Current.Get<List<Product>>(AppSettingsKeyNames.Basket);
            if (basketProducts != null)
            {
                Deployment.Current.Dispatcher.BeginInvoke(() => Products.Clear());

                decimal totalAmount = 0M;

                foreach (var p in basketProducts)
                {
                    totalAmount += p.Price;
                    var viewModel = new ProductViewModel(p);
                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        Products.Add(viewModel);
                    });
                    System.Threading.Thread.Sleep(20);
                }

                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    TotalPrice = string.Format(new CultureInfo("fr-fr"), "{0:C}", totalAmount);
                    _areProductsLoaded = true;
                });
            }
            else
            {
                ToastService.Instance.ShowNotification(ToastType.Error, "Votre panier a expiré");
                NavigationService.GoBack();
            }
        }

        private void ValidateNewAddress()
        {
            bool isValidAddress = true;

            NewAddress = new Address
            {
                Label = "Boulot 2",
                FirstName = _Customer.FirstName,
                LastName = _Customer.LastName,
                Street = "41 Quai du Président Roosevelt",
                City = "Issy-Les-Moulineaux",
                ZipCode = 92130
            };

            if (!isValidAddress)
            {
                //TODO Something
            }
        }

        #endregion
    }
}
